﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.LedgerEntry
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.IO;
using System.Text;

namespace Microsoft.InfoCards
{
  internal class LedgerEntry
  {
    private DateTime m_disclosureDate = DateTime.MinValue;
    private const int InvalidRow = 0;
    private const byte Version = 1;
    private const byte m_marker = 29;
    private bool m_isDirty;
    private string m_recipientId;
    private Recipient m_recipient;
    private byte[] m_subjectKey;
    private string[] m_disclosedClaims;
    private Uri m_infoCardId;
    private string m_immediateRecipientOrgId;
    private int m_rowId;

    public LedgerEntry(Stream stream, StoreConnection connection)
    {
      InfoCardTrace.Assert(null != stream, " Null input stream");
      InfoCardTrace.Assert(null != connection, "Null storeconnection");
      this.m_isDirty = false;
      this.Deserialize(stream);
      DataRow singleRow = connection.GetSingleRow(new QueryParameter("ix_objecttype", new object[1]
      {
        (object) -3
      }), new QueryParameter("ix_name", new object[1]
      {
        (object) this.m_recipientId
      }));
      InfoCardTrace.Assert(null != singleRow, "Recipient should always exist in store before a ledger entry is created ");
      if (singleRow != null)
        this.m_recipient = new Recipient((Stream) new MemoryStream(singleRow.GetDataField()));
      this.ThrowIfNotComplete();
    }

    public static LedgerEntry NewLedgerEntry(
      Uri infoCardId,
      Recipient recipient,
      byte[] masterKey,
      string immediateTokenRecipientOrganizationIdentifier)
    {
      return new LedgerEntry(infoCardId, recipient, masterKey, immediateTokenRecipientOrganizationIdentifier);
    }

    public LedgerEntry(
      Uri infoCardId,
      Recipient recipient,
      byte[] masterKey,
      string immediateTokenRecipientOrganizationIdentifier)
    {
      InfoCardTrace.Assert(null != recipient, "Null recipient");
      InfoCardTrace.Assert((Uri) null != infoCardId, "Null infocard ID");
      this.m_isDirty = true;
      this.m_infoCardId = infoCardId;
      this.m_disclosureDate = DateTime.Now;
      this.m_recipient = recipient;
      this.m_recipientId = recipient.RecipientId;
      this.m_immediateRecipientOrgId = immediateTokenRecipientOrganizationIdentifier;
      this.m_subjectKey = RsaKeyGen.CreateRsaKeyPairX931(masterKey, Convert.FromBase64String(immediateTokenRecipientOrganizationIdentifier));
      this.ThrowIfNotComplete();
    }

    public bool CheckAndUpdateSubjectKey(string immediateTokenRecipientOrgId, byte[] masterKey)
    {
      if (!(this.m_immediateRecipientOrgId != immediateTokenRecipientOrgId))
        return false;
      this.m_immediateRecipientOrgId = immediateTokenRecipientOrgId;
      this.m_subjectKey = RsaKeyGen.CreateRsaKeyPairX931(masterKey, Convert.FromBase64String(immediateTokenRecipientOrgId));
      return true;
    }

    public bool IsDirty
    {
      get
      {
        return this.m_isDirty;
      }
    }

    public DateTime DisclosureDate
    {
      set
      {
        this.m_disclosureDate = value;
        this.m_isDirty = true;
      }
    }

    public byte[] SubjectKey
    {
      get
      {
        InfoCardTrace.Assert(!Utility.ArrayIsNullOrEmpty((Array) this.m_subjectKey), "SubjectKey not populated!");
        return this.m_subjectKey;
      }
    }

    public string[] DisclosedClaims
    {
      get
      {
        return this.m_disclosedClaims;
      }
      set
      {
        this.m_disclosedClaims = value;
        this.m_isDirty = true;
      }
    }

    public Recipient Recipient
    {
      get
      {
        return this.m_recipient;
      }
    }

    public Uri InfoCardId
    {
      get
      {
        return this.m_infoCardId;
      }
    }

    public void ThrowIfNotComplete()
    {
      if (this.m_immediateRecipientOrgId == null || this.m_recipientId == null || (Utility.ArrayIsNullOrEmpty((Array) this.m_subjectKey) || !((Uri) null != this.m_infoCardId)) || !(DateTime.MinValue != this.m_disclosureDate))
        throw InfoCardTrace.ThrowHelperError((Exception) new SerializationIncompleteException(this.GetType()));
    }

    public void Serialize(BinaryWriter writer)
    {
      this.ThrowIfNotComplete();
      writer.Write((byte) 1);
      writer.Write(this.m_disclosureDate.ToFileTimeUtc());
      Utility.SerializeString(writer, this.m_recipientId);
      Utility.SerializeString(writer, this.m_immediateRecipientOrgId);
      Utility.SerializeBytes(writer, this.m_subjectKey);
      Utility.SerializeUri(writer, this.m_infoCardId);
      writer.Write(this.m_disclosedClaims == null ? 0 : this.m_disclosedClaims.Length);
      if (this.m_disclosedClaims != null)
      {
        foreach (string disclosedClaim in this.m_disclosedClaims)
          Utility.SerializeString(writer, disclosedClaim);
      }
      writer.Write((byte) 29);
    }

    public void Deserialize(Stream stream)
    {
      BinaryReader reader = (BinaryReader) new InfoCardBinaryReader(stream, Encoding.Unicode);
      if ((byte) 1 != reader.ReadByte())
        InfoCardTrace.Assert(false, "version mismatch deserializing ledger");
      this.m_disclosureDate = DateTime.FromFileTimeUtc(reader.ReadInt64());
      this.m_recipientId = Utility.DeserializeString(reader);
      this.m_immediateRecipientOrgId = Utility.DeserializeString(reader);
      this.m_subjectKey = reader.ReadBytes(reader.ReadInt32());
      this.m_infoCardId = Utility.DeserializeUri(reader);
      int length = reader.ReadInt32();
      if (length > 0)
      {
        this.m_disclosedClaims = new string[length];
        for (int index = 0; index < length; ++index)
          this.m_disclosedClaims[index] = Utility.DeserializeString(reader);
      }
      if ((byte) 29 != reader.ReadByte())
        InfoCardTrace.Assert(false, "Invalid stream detected deserializing ledger");
      this.ThrowIfNotComplete();
      this.m_isDirty = false;
    }

    public void Save(StoreConnection con)
    {
      DataRow row = this.TryGetRow(con, QueryDetails.FullHeader);
      if (row == null)
      {
        row = new DataRow();
        row.ObjectType = -1;
        row.GlobalId = (GlobalId) Guid.NewGuid();
      }
      row.SetIndexValue("ix_parentid", (object) GlobalId.DeriveFrom(this.m_infoCardId.ToString()));
      row.SetIndexValue("ix_name", (object) this.m_recipientId);
      MemoryStream memoryStream = new MemoryStream();
      this.Serialize(new BinaryWriter((Stream) memoryStream, Encoding.Unicode));
      row.SetDataField(memoryStream.ToArray());
      con.GetSingleRow(QueryDetails.FullHeader, new QueryParameter("ix_objecttype", new object[1]
      {
        (object) -3
      }), new QueryParameter("ix_name", new object[1]
      {
        (object) this.m_recipientId
      }));
      if (row != null)
        con.Save(row);
      else
        InfoCardTrace.Assert(false, "Currupt store - no recipient found for ledger");
      this.m_rowId = row.LocalId;
      this.m_isDirty = false;
    }

    public override string ToString()
    {
      return base.ToString();
    }

    protected DataRow TryGetRow(StoreConnection con, QueryDetails details)
    {
      InfoCardTrace.Assert((Uri) null != this.m_infoCardId, "populate infocard before retrieving ledger");
      return con.GetSingleRow(QueryDetails.FullHeader, new QueryParameter("ix_objecttype", new object[1]
      {
        (object) -1
      }), new QueryParameter("ix_name", new object[1]
      {
        (object) this.m_recipientId
      }), new QueryParameter("ix_parentid", new object[1]
      {
        (object) GlobalId.DeriveFrom(this.m_infoCardId.ToString())
      }));
    }
  }
}
